package xyz.ck.commons.interval;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import xyz.ck.commons.util.SyntaxException;

public class IntervalHelper {
	
	/**
	 * eg: [1,5], [-11,-12)
	 */
	public static final String ContinousIntervalRegex = "^\\s*[\\[,\\(]{1}\\s*\\d*\\s*,\\s*\\d*\\s*[\\],\\)]\\s*$";

	/**
	 * eg:1~5,-11~-12
	 */
	public static final String IntervalRegex = "^\\s*[-]?\\d*\\s*,\\s*[-]?\\d*\\s*$";

	/**
	 * 将Interval全部展开为 IntervalUnit
	 * 
	 * @param <T>
	 * 
	 * @param interval
	 * @return
	 */
	public static <T> List<IntervalUnit<T>> develop(Interval<T> interval) {
		if (interval == null) {
			return null;
		}
		if (interval.isGroup()) {
			IntervalGroup<T> group = (IntervalGroup<T>) interval;
			try {
				@SuppressWarnings("unchecked")
				IntervalGroup<T> clone = (IntervalGroup<T>) group.clone();
				return clone.getUnits();
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
				List<IntervalUnit<T>> dest = new ArrayList<IntervalUnit<T>>();
				for (IntervalUnit<T> unit : group.getUnits()) {
					try {
						@SuppressWarnings("unchecked")
						IntervalUnit<T> clone = (IntervalUnit<T>) unit.clone();
						dest.add(clone);
					} catch (CloneNotSupportedException e1) {
						e1.printStackTrace();
						dest.add(new IntervalUnit<T>(unit.min(), unit.max()));
					}
				}
				return dest;
			}
		} else if (interval.isUnit()) {
			List<IntervalUnit<T>> dest = new ArrayList<IntervalUnit<T>>();
			IntervalUnit<T> unit = (IntervalUnit<T>) interval;
			try {
				@SuppressWarnings({ "unchecked" })
				IntervalUnit<T> clone = (IntervalUnit<T>) unit.clone();
				dest.add(clone);
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
				IntervalUnit<T> clone = new IntervalUnit<T>(unit.min(),
						unit.max());
				dest.add(clone);
			}
			return dest;
		} else {
			throw new ClassCastException("Unknow Interval Type! only!");
		}

	}

	public static Interval<Integer> getIntegerInterval(int min, int max) {
		return new IntervalUnit<Integer>(min, max);
	}

	/**
	 * eq: 1~5
	 * 
	 * @see Constant.Regex_Eff1
	 * @param strs
	 * @return
	 */
	public static Interval<Integer> getIntegerInterval(String strs) {
		if (strs == null || strs.isEmpty()) {
			return null;
		}

		String[] items = strs.split(",");
		if (items == null) {
			return null;
		}

		List<Interval<Integer>> lists = new ArrayList<Interval<Integer>>();
		for (int i = 0; i < items.length; i++) {
			Interval<Integer> unit = newIntegerInterval(items[i]);
			lists.add(unit);
		}
		return IntervalGroup.unions(lists);
	}

	public static List<Integer> getIntegerIntervalValues(
			Interval<Integer> interval) {

		if (interval == null || interval.isEmpty()) {
			return Collections.emptyList();
		}
		if (interval.isContinuous()) {
			throw new IntervalException(
					"Continuous interval can not list values!");
		}
		if (interval.isGroup()) {
			IntervalGroup<Integer> group = (IntervalGroup<Integer>) interval;
			List<IntervalUnit<Integer>> units = group.getUnits();
			List<Integer> intList = new ArrayList<Integer>();
			for (IntervalUnit<Integer> unit : units) {
				List<Integer> values = unit.listValues(0);
				intList.addAll(values);
			}
			return intList;
		}

		if (interval instanceof IntervalUnit) {
			IntervalUnit<Integer> ii = (IntervalUnit<Integer>) interval;
			return ii.listValues(0);
		}

		return null;
	}

	public static <T> Interval<T> joinIntervals(
			Collection<Interval<T>> intervals) {
		return IntervalGroup.unions(intervals);
	}

	/**
	 * 
	 * @param strs
	 * @return
	 */
	private static Interval<Integer> newIntegerInterval(String strs) {
		if (strs == null || strs.isEmpty()) {
			return null;
		}

		strs = strs.replaceAll("\\+", "-" + Integer.MAX_VALUE);
		String[] items = strs.split("~");
		if (items == null) {
			return null;
		}
		if (items.length == 1) {
			int num = Integer.parseInt(items[0].trim());
			return new IntervalUnit<Integer>(num, num);

		}

		if (items.length == 2) {
			int min = Integer.parseInt(items[0].trim());
			int max = Integer.parseInt(items[1].trim());
			return new IntervalUnit<Integer>(min, max);

		}
		throw new SyntaxException("syntax Error: espect 10-20 or 15 an so on! ");
	}

	public static void main(String[] args) {
		Interval<Integer> interval = getIntegerInterval("177~876,-9~15,88~89,22,");
		Interval<Integer> interval2 = getIntegerInterval("8~66,277");
		System.out.printf("(%s) minus (%s) = (%s)\n", interval, interval2,
				interval.minus(interval2));
		System.out.printf("(%s) join (%s) = (%s)\n", interval, interval2,
				interval.union(interval2));
		System.out.printf("(%s) intersect (%s) = (%s)\n", interval, interval2,
				interval.intersect(interval2));
		System.out.printf("(%s) isContains (%s) : %s\n", interval, interval2,
				interval.isContains(interval2));
	}
}
